package com.itaming.lycheeframework.jackson.provider;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.CacheProvider;
import com.fasterxml.jackson.databind.ser.DefaultSerializerProvider;
import com.fasterxml.jackson.databind.ser.SerializerFactory;
import com.itaming.lycheeframework.jackson.serializer.NullToEmptySerializers;

import java.io.Serial;
import java.time.OffsetDateTime;
import java.time.temporal.TemporalAccessor;
import java.util.Collection;
import java.util.Date;

/**
 * 序列化器提供者
 * <p>
 * 提供了序列化时对<code>null</code>值的处理，用来替换<code>Jackson</code>默认的实现{@link DefaultSerializerProvider.Impl}
 *
 * @author A.Ming
 */
public class LycheeSerializerProvider extends DefaultSerializerProvider {

    @Serial
    private static final long serialVersionUID = 1L;

    public LycheeSerializerProvider() {
    }

    public LycheeSerializerProvider(LycheeSerializerProvider src) {
        super(src);
    }

    protected LycheeSerializerProvider(SerializerProvider src, SerializationConfig config, SerializerFactory f) {
        super(src, config, f);
    }

    protected LycheeSerializerProvider(LycheeSerializerProvider src, CacheProvider cp) {
        super(src, cp);
    }

    public DefaultSerializerProvider copy() {
        return this.getClass() != LycheeSerializerProvider.class ? super.copy() : new LycheeSerializerProvider(this);
    }

    public LycheeSerializerProvider createInstance(SerializationConfig config, SerializerFactory f) {
        return new LycheeSerializerProvider(this, config, f);
    }

    @Override
    public DefaultSerializerProvider withCaches(CacheProvider cacheProvider) {
        return new LycheeSerializerProvider(this, cacheProvider);
    }

    @Override
    public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) {
        // 如果字段已配置具体的序列化器，则不会进入到此方法
        return getSerializer(property.getType());
    }

    /**
     * 获取指定类型的序列化器
     *
     * @param type 类型
     * @return 序列化器
     */
    private JsonSerializer<Object> getSerializer(JavaType type) {
        Class<?> clazz = type.getRawClass();

        // 字符串
        if (type.isTypeOrSubTypeOf(Character.class) || type.isTypeOrSubTypeOf(String.class)) {
            return NullToEmptySerializers.STRING_JSON_SERIALIZER;
        }

        // 数字
        if (type.isTypeOrSubTypeOf(Number.class)) {
            return NullToEmptySerializers.NUMBER_JSON_SERIALIZER;
        }

        // 布尔
        if (type.isTypeOrSubTypeOf(Boolean.class)) {
            return NullToEmptySerializers.BOOLEAN_JSON_SERIALIZER;
        }

        // 数组
        if (type.isArrayType() || clazz.isArray() || type.isTypeOrSubTypeOf(Collection.class)) {
            return NullToEmptySerializers.ARRAY_JSON_SERIALIZER;
        }

        // 日期
        if (type.isTypeOrSubTypeOf(OffsetDateTime.class) || type.isTypeOrSubTypeOf(Date.class) || type.isTypeOrSubTypeOf(TemporalAccessor.class)) {
            return NullToEmptySerializers.STRING_JSON_SERIALIZER;
        }

        // 对象
        return NullToEmptySerializers.OBJECT_JSON_SERIALIZER;
    }

}
